Skip to content

MkFootNotes

Show source on GitHub

Node containing a list of MkFootNotes.

Bases: MkContainer

__init__

__init__(
    footnotes: Mapping[int, str | mk.MkNode] | list[MkFootNote] | list[str] | None = None,
    **kwargs: Any
)

Parameters:

Name Type Description Default
footnotes Mapping[int, str | MkNode] | list[MkFootNote] | list[str] | None

Footnotes data (Can be given in different shapes)

None
kwargs Any

Keyword arguments passed to parent

{}
Name Children Inherits
MkContainer
mknodes.basenodes.mkcontainer
A node containing other MkNodes.
graph TD
  94854583025616["mkfootnotes.MkFootNotes"]
  94854582919984["mkcontainer.MkContainer"]
  94854582916880["mknode.MkNode"]
  94854582838576["node.Node"]
  140544995341632["builtins.object"]
  94854582919984 --> 94854583025616
  94854582916880 --> 94854582919984
  94854582838576 --> 94854582916880
  140544995341632 --> 94854582838576
/home/runner/work/mknodes/mknodes/mknodes/basenodes/mkfootnotes/metadata.toml
[metadata]
icon = "octicon:list-ordered-16"
name = "MkFootNotes"

[requirements.extension.footnotes]

[examples.regular]
title = "Regular"
python = """
node = MkFootNotes()
page += "The MkFootNotes node aggregates footnotes[^1]."
node[1] = r"Footnotes are numbered, can be set via `__setitem__`."
node[2] = r"They can also get nested[^3]."
node[3] = mk.MkAdmonition("And they can also contain other Markdown.")
node
"""

[fragments.footnote]
template = """
[^{{ footnote.num }}]
{{ node.items | join("\n") | indent(first=True) }}
"""

[output.markdown]
template = """
{{ node.items | sort(attribute="num") | join }}
"""

[output.rst]
template = """
.. rubric:: Footnotes

{% for item in node.items | sort(attribute="num") %}
.. {{ item }}
"""
mknodes.basenodes.mkfootnotes.MkFootNotes
class MkFootNotes(mkcontainer.MkContainer):
    """Node containing a list of MkFootNotes."""

    items: list[MkFootNote]
    ICON = "octicons/list-ordered-16"
    REQUIRED_EXTENSIONS = [resources.Extension("footnotes")]

    def __init__(
        self,
        footnotes: (
            Mapping[int, str | mk.MkNode] | list[MkFootNote] | list[str] | None
        ) = None,
        **kwargs: Any,
    ):
        """Constructor.

        Arguments:
            footnotes: Footnotes data (Can be given in different shapes)
            kwargs: Keyword arguments passed to parent
        """
        match footnotes:
            case None:
                items = []
            case list():
                items = [
                    (
                        ann if isinstance(ann, MkFootNote) else MkFootNote(i, ann)  # type: ignore
                    )
                    for i, ann in enumerate(footnotes, start=1)
                ]
            case Mapping():
                items = [MkFootNote(k, content=v) for k, v in footnotes.items()]
            case _:
                raise TypeError(footnotes)
        super().__init__(content=items, **kwargs)

    def __repr__(self):
        notes: list[mk.MkNode | str] = []
        for item in self.items:
            if len(item.items) == 1 and isinstance(item.items[0], mktext.MkText):
                notes.append(str(item.items[0]))
            elif len(item.items) == 1:
                notes.append(item.items[0])
            else:
                notes.append(item)
        return reprhelpers.get_repr(self, footnotes=notes)

    def __getitem__(self, index: int):
        for node in self.items:
            if node.num == index:
                return node
        raise IndexError(index)

    def __contains__(self, item: int | MkFootNote) -> bool:
        match item:
            case MkFootNote():
                return item in self.items
            case int():
                return any(i.num == item for i in self.items)
            case _:
                raise TypeError(item)

    def _get_item_pos(self, num: int) -> int:
        item = next(i for i in self.items if i.num == num)
        return self.items.index(item)

    def __setitem__(self, index: int, value: mk.MkNode | str):
        match value:
            case MkFootNote():
                node = value
            case _:
                node = MkFootNote(index, content=value, parent=self)
        if index in self:
            pos = self._get_item_pos(index)
            self.items[pos] = node
        else:
            self.items.append(node)

    def _to_markdown(self) -> str:
        if not self.items:
            return ""
        items = sorted(self.items, key=lambda x: x.num)
        return "".join(i.to_markdown() for i in items)